#include <iostream>  
#include <sys/epoll.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <unistd.h>  
#include <fcntl.h>  
#include <strings.h>
  
#define MAX_EVENTS 10  
#define PORT 8080
  
int main() {  
    int server_fd, client_fd, epoll_fd, nfds;  
    struct sockaddr_in server_addr, client_addr;  
    socklen_t client_len = sizeof(client_addr);  
    struct epoll_event ev, events[MAX_EVENTS];  
    int i;  
  
    // 创建socket  
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
        perror("socket");  
        return 1;  
    }  
  
    // 设置socket为非阻塞  
    int flags = fcntl(server_fd, F_GETFL, 0);  
    if (flags == -1) {  
        perror("fcntl get flags");  
        return 1;  
    }  
    if (fcntl(server_fd, F_SETFL, flags | O_NONBLOCK) == -1) {  
        perror("fcntl set flags");  
        return 1;  
    }  
  
    // 绑定socket到端口8080  
    server_addr.sin_family = AF_INET;  
    server_addr.sin_port = htons(PORT);  
    server_addr.sin_addr.s_addr = INADDR_ANY;  
    bzero(&(server_addr.sin_zero), 8);  
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {  
        perror("bind");  
        return 1;  
    }  
  
    // 监听socket  
    if (listen(server_fd, 10) == -1) {  
        perror("listen");  
        return 1;  
    }  
  
    // 创建epoll实例  
    if ((epoll_fd = epoll_create(1)) == -1) {  
        perror("epoll_create");  
        return 1;  
    }  
  
    // 注册监听socket的读事件到epoll  
    ev.events = EPOLLIN;  
    ev.data.fd = server_fd;  
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev) == -1) {  
        perror("epoll_ctl server_fd");  
        return 1;  
    }  
  
    while(true) {  
        // 等待事件  
        if ((nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1)) == -1) {  
            perror("epoll_wait");  
            return 1;  
        }  
  
        // 处理事件  
        for (i = 0; i < nfds; ++i) {  
            if (events[i].data.fd == server_fd) {  
                // 处理新的连接  
                if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len)) == -1) {  
                    perror("accept");  
                    continue;  
                }  
                // 设置新连接为非阻塞  
                flags = fcntl(client_fd, F_GETFL, 0);  
                if (flags == -1) {  
                    perror("fcntl get flags");  
                    close(client_fd);  
                    continue;  
                }  
                if (fcntl(client_fd, F_SETFL, flags | O_NONBLOCK) == -1) {  
                    perror("fcntl set flags");  
                    close(client_fd);  
                    continue;  
                }  
  
                // 注册新连接的读事件到epoll  
                ev.events = EPOLLIN;  
                ev.data.fd = client_fd;  
                if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) == -1) {  
                    perror("epoll_ctl client_fd");  
                    close(client_fd);  
                }  
  
                std::cout << "Accepted new connection from client " << client_fd << std::endl;  
            } else {  
                // 处理客户端数据  
                char buffer[1024];  
                ssize_t bytes = recv(events[i].data.fd, buffer, sizeof(buffer), 0);  
                if (bytes <= 0) {  
                    // 连接已关闭或错误，关闭socket并从epoll中移除  
                    close(events[i].data.fd);
                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
                    std::cout << "Client " << events[i].data.fd << " disconnected" << std::endl;
                } else {  
                    // 处理接收到的数据（此处简单打印到控制台）  
                    buffer[bytes] = '\0';  
                    std::cout << "Received from client " << events[i].data.fd << " : " << buffer << std::endl;  
  
                    // 发送响应给客户端（此处简单回显接收到的数据）  
                    send(events[i].data.fd, buffer, bytes, 0);  
                }  
            }  
        }  
    }  
  
    // 关闭epoll实例和服务器socket（实际上这行代码永远不会被执行，因为上面的循环是无限的）  
    close(epoll_fd);  
    close(server_fd);  
  
    return 0;  
}